/*
 * @FilePath: /etws-sxk2307/src/Uio/Uio.cpp
 * @Description:  
 * @Author: ipk518 && 18163976442@163.com
 * @Date: 2024-05-23 16:30:33
 * @LastEditors: ipk518 18163976442@163.com
 * @LastEditTime: 2024-08-29 17:35:32
 * Copyright    : G AUTOMOBILE RESEARCH INSTITUTE CO.,LTD Copyright (c) 2024.
 */

#include <sys/epoll.h>  
#include <unistd.h>  
#include <pthread.h>  
#include <queue>  
#include <mutex> 


#include "commHeader.h"
#include "Uio.h"
#include "math.h"
#include "Mem.h"
#include "Common.h"
#include "Server.h"
#include "getConfig.h"
#include "fftw.h"
/********************************************************************
 * 
 * 暗室打包结构4有效波位，+ 双极化
 * 
 * 2个字节外部触发总数+2字节任务波位数 + 2字节极化 
 * +触发1里面的第一个波位的H幅度+触发1里面的第二个波位的H幅度
 * +触发1里面的第三个波位的H幅度+触发1里面的第四个波位的H幅度
 * 
 * +触发1里面的第一个波位的V幅度+触发1里面的第二个波位的V幅度
 * +触发1里面的第三个波位的V幅度+触发1里面的第四个波位的V幅度
 * 
 * +触发1里面的第一个波位的H相位+触发1里面的第二个波位的H相位
 * +触发1里面的第三个波位的H相位+触发1里面的第四个波位的H相位
 * 
 * +触发1里面的第一个波位的V幅度+触发1里面的第二个波位的V相位
 * +触发1里面的第三个波位的V相位+触发1里面的第四个波位的V相位
 * 
 * +触发N
 * 
 * 
 * 
 * 
 * 
 * 
 * */

#define FFTW_ENABLE     0

//暗室上报数组
vector<uint8_t> DarktsUpdateVct;
//校准结构
struct txCalibrationFrame txCalibSrc;
struct rxCalibrationFrame rxCalibSrc;



struct rxDbfObsFrame m_rxDbfObs;
vector<uint8_t> rxDbfObsData;

struct rxCalibrationFrame m_rxObs;
vector<uint8_t> rxObsData;

struct txObsFrame m_txObs;
struct txObsUpdate m_txUpdateObs;
vector<uint8_t> txObsData;

struct adcObsFrame m_adcObs;
vector<uint8_t> adcObsData;

//暗室数据提取分析
struct darktsFrame darktsPackage[32];
//暗室数据缓存
struct darktsFrame darktsPing[16];
struct darktsFrame darktsPong[16];
//暗室数据缓存队列
std::queue<struct darktsFrame> iq0Queue;
std::queue<struct darktsFrame> iq1Queue;

std::mutex g_iq0Mutex;
std::mutex g_iq1Mutex;
std::condition_variable g_uio0Cond;
std::condition_variable g_uio1Cond;

#define FIRE_POLAR_H    0
#define FIRE_POLAR_V    1


const char* irq0Name[] = {
    INTC_H_MANUALSEND,
    INTC_V_MANUALSEND,
    INTC_AUTO,
    INTC_H_MANUALRECVICE,
    INTC_V_MANUALRECVICE,
    INTC_IQ0_TWOBUF,
    INTC_IQ1_TWOBUF,
    INTC_JESD204
};

const char* irq1Name[] = {
    INTC_DMA_ERR,
    INTC_CALI_DMA_ERR,
    INTC_AD_OBSDMA,
    INTC_DBF_OBSDMA,
    INTC_AXI_IRQ,
    INTC_AXI_GPIO,
    INTC_AXI_GPS,
    INTC_AXI_SERVO
};

const char* axiIntcName[] = {
    AXIINTC_DAC_DMA,
    AXIINTC_DAC_0,
    AXIINTC_DAC_1,
    AXIINTC_DMA_TWOBUF,
    AXIINTC_CDMA_0
};



Uio::Uio()
{
    m_workStatus = uio_noReply;
    sem_init(&g_packageTask, 0, 0);
    sem_init(&g_obsSem, 0, 0);
    sem_init(&g_dbfSem, 0, 0);
}

Uio::~Uio()
{
    m_isRunning = false;
    if(m_pub != nullptr) {
        delete m_pub;
    }

    if (irq0Fd != nullptr) {
        irq0Fd->join();
        irq0Fd = nullptr;
        irq1Fd->join();
        irq1Fd = nullptr;
    }
    if (workFd!= nullptr) {
        workFd->join();
        workFd = nullptr;
    }
    if (topWorkFd != nullptr) {
        topWorkFd->join();
        topWorkFd = nullptr;
    }
    if (bottomWorkFd != nullptr) {
        bottomWorkFd->join();
        bottomWorkFd = nullptr;
    }

    if(packagedFd != nullptr) {
        packagedFd->join();
        packagedFd = nullptr;
    }

    if(obsTxFd!= nullptr) {
        obsTxFd->join();
        obsTxFd = nullptr;
    }

    if(m_darktsAddr != nullptr) {
        mmapFree(m_memFile,m_darktsAddr,DARK_CAP);
    }
    close(m_memFile);
    
    sem_destroy(&g_packageTask);
    sem_destroy(&g_obsSem);
    sem_destroy(&g_dbfSem);
}

/**
 * @description: 幅度计算
 * @param {uint8_t} *q_date(虚部分量)
 * @param {uint8_t} *i_date(实部分量)
 * @return {*}
 */
static double math_amp_calculate(int q_date, int i_date)
{
    double amp;
    int Q_date,I_date;
    Q_date = q_date;
    I_date = i_date;
    amp = (double)sqrt(pow(Q_date, 2) + pow(I_date, 2));
    amp = 20 * log10(abs(amp)); // 换DB
    
    return amp;
}

/*** 
 * @description: 角度转换
 * @param {int} angle
 * @return {*}
 */
static float convert_angle(float angle) {  
    // 确保输入的角度在 0 到 360 范围内  
    float m_angle = angle; 
    // 如果角度为 360，则转换为 0  
    if (m_angle >= 360.0) {  
        m_angle = 0;  
    }  
    // 转换为 -180 到 180 范围  
    if (m_angle > 180.0) {  
        m_angle -= 360.0;  
    }  
    return m_angle;  
}  

/**
 * @description: 相位计算[0, 360)  2025-3-1
 * @param {uint8_t} *q_date(虚部分量)
 * @param {uint8_t} *i_date(实部分量)
 * @return {*}
 */
static double math_phase_calculate(int q_date, int i_date)
{
    double phase;
    // int Q_date,I_date;
    // Q_date = q_date;
    // I_date = i_date;
    // phase = (double)(atan2(Q_date, I_date) * 180 / M_PI + 180);

     // 检查虚部和实部是否均为零  
    // if (q_date == 0 && i_date == 0) {
    //     return 0; // 或者根据需求处分，那么这里可以返回-1或其他特定值表示无效  
    // }

    // 使用atan2计算相位，并调整范围到 [0, 360)  
    phase = atan2(q_date, i_date) * 180.0 / M_PI; // 转换为度  
    return fmod(phase + 360.0, 360.0); // 使相位保持在 [0, 360) 范围内

    // return phase;
}

/**
 * @brief: 初始化所有UIO中断
 * @return {*}
 */
bool Uio::Init()
{
    m_memFile = openMem();
    m_darktsAddr = mmapMalloc(m_memFile,DRAK_ROOM_BASEADDR,DARK_CAP);
    if(m_darktsAddr == nullptr) {
        return false;
    }
    //去掉JESD204B中断
    for(int i=0; i < (CALIB_FILES - 1); i++) {
        calibFd[i] = openUio(irq0Name[i]);
        if (calibFd[i] < 0) {
            return false;
        }
    }
    for(int i = 0; i < INTC_FILES - 4; i++)
    {
        intcFd[i] = openUio(irq1Name[i]);
        if (intcFd[i] < 0) {
            return false;
        }
    }
    // for(int i=0; i < AXIINTC_FILES; i++)
    // {
    //     axiFd[i] = openUio(axiIntcName[i]);
    //     if (axiFd[i] < 0) {
    //         return false;
    //     }
    // }

    m_pub = new transmit();
    m_isRunning = true;
    irq0Fd = new std::thread(std::bind(&Uio::irq0Handle, this));
    irq1Fd = new std::thread(std::bind(&Uio::irq1Handle, this));
    workFd = new std::thread(std::bind(&Uio::work, this));
    topWorkFd = new std::thread(std::bind(&Uio::topHalfWork, this));
    bottomWorkFd = new std::thread(std::bind(&Uio::bottomHalfWork, this));
    packagedFd = new std::thread(std::bind(&Uio::packageTask, this));
    obsTxFd = new std::thread(std::bind(&Uio::txObsWork, this));
    return true;
}

int Uio::openUio(const char* filename)
{
    if (filename == nullptr)
        return -1;

    int fd = open(filename, O_RDWR);
    if (fd < 1)
    {
        qlog_i("无效的 UIO device file:%s.\n", filename);
        return -1;
    }
    qlog_i("%s init sucessfully", filename);
    return fd;
}

void Uio::Sendto(uioMode m)
{
    vector<uint8_t> buf;
    uint16_t data[64];
    // uint16_t m_mode = Server::Instance().m_sxk.m_calibParam.m_calibMode;//多一个校准频点上报,X05不用
    uint16_t m_freq = Server::Instance().m_sxk.m_calibParam.m_calibFreq;
    uint8_t m_tmp[2];
    memcpy(m_tmp,(uint8_t *)&m_freq,2);
    for(int i=0;i<32;i++) {
        data[i] = static_cast<uint16_t>(m_amp[i]*100);
    }
    for(int i=32,j=0;i<64;i++,j++) {
        data[i] = static_cast<uint16_t>(m_phase[j]*10);
    }
    
    buf.push_back(m_tmp[0]);
    buf.push_back(m_tmp[1]);
    buf.insert(buf.end(), (uint8_t*)data, (uint8_t*)data + sizeof(data));

    m_pub->pulish(m,buf);

}


void Uio::irq0Handle(Uio *argc)
{
    int i = 0, j = 0, k = 0, icount, nCount = 30;
    int irq_on = 1,m_ready = 0, real_read = 0;
    struct pollfd fds[CALIB_FILES - 1];
    int Q_date = 0, I_date = 0;
    double timeout=0;
    int64_t g_iclock0 = 0,g_iclock1 = 0;
    pthread_setname_np(pthread_self(),"uioHandle");
    for (i = 0; i < CALIB_FILES - 1; i++)
    {
        fds[i].fd = argc->calibFd[i];
        fds[i].events = POLLIN;                    // 请求类型是 普通或优先级带数据可读
        if (write(fds[i].fd, &irq_on, sizeof(irq_on)) < 0) {
            qlog_e("calib_filp error:%d",argc->calibFd[i]);
        } // 使能中断，每次触发后都需要重新使能
    }
    while (argc->m_isRunning)
    {
        m_ready = poll(fds, CALIB_FILES-1, -1);
        if (m_ready == -1)
        {
            perror("poll error:");
        }
        //TODO:2024-12-05 取值30
        nCount = readIntValue("paramsConfig","simplePoint",Server::Instance().m_configPath.c_str());
        if(nCount <= 0) {
            nCount = 30;
        }
        for (i = 0; i < CALIB_FILES - 1; i++)
        {
            if (fds[i].revents & POLLIN)
            {
                // qlog_n("cali interrupt :%d", i);
                if (i == 0 || i == 1)
                { // H极化发射手动校准完成中断-//V极化发射手动校准完成中断
                    qlog_i("发射校准中断已产生..");

                    memset(argc->m_amp, 0, sizeof(argc->m_amp));  
                    memset(argc->m_phase, 0, sizeof(argc->m_phase));  
                    for (k = 0; k < 32; k++)  //按每0x8000偏移取每个通道的IQ值
                    {  
                        txCalibSrc.m_simpleNum = 0;  
                        txCalibSrc.m_prtNum = 0;  
                        
                        memorySwap(argc->m_memFile, ((TX_CALIB_BASEADDR + TX_CALIB_OFFSET * i) + TX_CALIB_CHN_OFFSET * k),  
                            (unsigned char *)&txCalibSrc, sizeof(txCalibSrc), nullptr, 0);  
#if (FFTW_ENABLE == 0)
                        I_date = (int)(txCalibSrc.m_iqBuffer[nCount] & 0xffffffff);  
                        Q_date = (int)((txCalibSrc.m_iqBuffer[nCount] >> 32) & 0xffffffff);  

                        argc->m_amp[k] = math_amp_calculate(Q_date, I_date);  
                        argc->m_phase[k] = math_phase_calculate(Q_date, I_date); 
                        
#else                        
                        auto result= fftTask(txCalibSrc.m_simpleNum,txCalibSrc.m_iqBuffer);

                        argc->m_amp[k] = result.first;
                        argc->m_phase[k] = result.second;
#endif
                        // if(k == 0 || k == 31) {
                        //     printf("开始------校准通道%d,有效采样点数:%d------\n",k,txCalibSrc.m_simpleNum);
                        //     printf("{ ");
                        //     for(int i=0;i<256;i++)
                        //     {
                        //         printf("0x%lx, ",txCalibSrc.m_iqBuffer[i]);
                        //     }
                        //     printf(" }\n");
                        //     printf("结束------校准通道%d------\n",k);
                        // }
                    }  

                    if (i == 0) {  
                        argc->Sendto(uio_h_sendPolar);  
                    } else {  
                        argc->Sendto(uio_v_sendPolar);  
                    }  
                }
                if (i == 2)
                { // 自动校准完成
                    qlog_i("自动校准中断已产生..");
                    // 自动校准中断读取HV收发校准两个
                    argc->recvSendCalibreation(uio_autoMode);

                }
                if (i == 3 || i == 4)
                {  // H接收手动校准完成中断-//V接收手动校准完成中断
                    qlog_i("接收手动校准中断已产生..");
                    k = (i == 3)?0:1;
                    memset(argc->m_amp, 0, sizeof(argc->m_amp));  
                    memset(argc->m_phase, 0, sizeof(argc->m_phase));
                    rxCalibSrc.m_simple = 0;  
                    rxCalibSrc.m_prtNum = 0;    
                    memorySwap(argc->m_memFile, (RX_CALIB_BASEADDR + RX_CALIB_OFFSET * k),  
                            (unsigned char *)&rxCalibSrc, sizeof(rxCalibSrc), nullptr, 0); 

                    //TODO:2024-12-05 取值30
#if (FFTW_ENABLE == 0)
                    for(j = 0;j<32; j++) {
                        I_date = (int)(rxCalibSrc.m_iqBuffer[nCount][j] & 0xffffffff);  
                        Q_date = (int)((rxCalibSrc.m_iqBuffer[nCount][j] >> 32) & 0xffffffff);  

                        argc->m_amp[j] = math_amp_calculate(Q_date, I_date);  
                        argc->m_phase[j] = math_phase_calculate(Q_date, I_date); 
                    }
#else
                    //接收校准数据缓存
                    vector<uint64_t>rxCalibChannelData;
                    rxCalibChannelData.resize(rxCalibSrc.m_simple);
                    for (j = 0;j<32;j++) {
                        for(int l=10;l<rxCalibSrc.m_simple;l++) {
                            rxCalibChannelData[l] = rxCalibSrc.m_iqBuffer[l][j];
                        }
                        auto result= fftTask(rxCalibSrc.m_simple,rxCalibChannelData.data());
                        argc->m_amp[j] = result.first;
                        argc->m_phase[j] = result.second;
                    }
                    rxCalibChannelData.clear();
#endif
                    // for(int j = 0;j<32;j++) {
                    //     printf("开始------接收校准通道%d,有效采样点数:%d------\n",j,rxCalibSrc.m_simple);
                    //     printf("{ ");
                    //     for(int i=0;i<rxCalibSrc.m_simple;i++)
                    //     {
                    //         printf("0x%lx, ",rxCalibSrc.m_iqBuffer[i][j]);
                    //     }
                    //     printf(" }\n");
                    //     printf("结束------接收校准通道%d------\n",j);
                    // }
                    
                    
                    if (k == 0) {
                        argc->Sendto(uio_h_recvicePolar);
                    } else {
                        argc->Sendto(uio_v_recvicePolar);
                    }

                }
                if( i == 5)
                {//观测通道乒乓区0满中断
                    timeout = (double)((time_now() - g_iclock0) / 1000);  
                    qlog_n("5:clock=%0.3fms", (timeout / 1000));  
                    g_iclock0 = time_now();  
                    
                    {  
                        std::unique_lock<std::mutex> m_guard(g_iq0Mutex);  
                        
                        for (j = 0; j < 16; j++) {  
                            memRead((unsigned long *)&darktsPing[j], argc->m_darktsAddr, DARK_OFFSET*j, sizeof(struct darktsFrame));
                            if (iq0Queue.size() > DARK_QUEUE_MAX) {  
                                iq0Queue.pop();  
                            }  
                            iq0Queue.push(darktsPing[j]);  
                            
                        }  
                    }  
                    g_uio0Cond.notify_one();  
                        
                }
                if( i== 6)
                {//观测通道乒乓区1满中断
                    timeout = (double)((time_now() - g_iclock1) / 1000);  
                    qlog_n("6:clock=%0.3fms", (timeout / 1000));  
                    g_iclock1 = time_now();   
                    
                    {  
                        std::unique_lock<std::mutex> m_guard(g_iq1Mutex); 

                        for (k = 16,j = 0; k < 32; k++,j++) {  
                            memRead((unsigned long *)&darktsPong[j], argc->m_darktsAddr, DARK_OFFSET*k, sizeof(struct darktsFrame));  
                            if (iq1Queue.size() > DARK_QUEUE_MAX) {  
                                iq1Queue.pop();  
                            }  
                            iq1Queue.push(darktsPong[j]);  
                            
                        }  
                    }  
                    g_uio1Cond.notify_one();  
                }
                real_read = read(fds[i].fd, &icount, 4);
                if (real_read != 4){
                    qlog_e("uio read:%d", real_read);
                }
                if (write(fds[i].fd, &irq_on, sizeof(irq_on)) < 0) {
                    qlog_e("enable irq:%d", fds[i].fd);
                }
            }
        }
    }
}


void Uio::recvSendCalibreation(uioMode m)
{
    int I_date = 0,Q_date = 0;
    int nCount = readIntValue("paramsConfig","simplePoint",Server::Instance().m_configPath.c_str());
    if(nCount <= 0) {
        nCount = 30;
    }
    //提取H极化发射自动校准数据
    memset(m_amp, 0, sizeof(m_amp));  
    memset(m_phase, 0, sizeof(m_phase));   
    for (int k = 0; k < 32; k++)  //按每0x8000偏移取每个通道的IQ值
    {  
        txCalibSrc.m_simpleNum = 0;  
        txCalibSrc.m_prtNum = 0;  
        
        memorySwap(m_memFile, ((TX_CALIB_BASEADDR + TX_CALIB_OFFSET * 2) + TX_CALIB_CHN_OFFSET * k),  
            (unsigned char *)&txCalibSrc, sizeof(txCalibSrc), nullptr, 0); 

#if (FFTW_ENABLE == 0)

        I_date = (int)(txCalibSrc.m_iqBuffer[nCount] & 0xffffffff);  
        Q_date = (int)((txCalibSrc.m_iqBuffer[nCount] >> 32) & 0xffffffff);  

        m_amp[k] = math_amp_calculate(Q_date, I_date);  
        m_phase[k] = math_phase_calculate(Q_date, I_date);  
#else
        auto result= fftTask(txCalibSrc.m_simpleNum,txCalibSrc.m_iqBuffer);

        m_amp[k] = result.first;
        m_phase[k] = result.second;
#endif
        // int x = (txCalibSrc.m_simpleNum > 2000)?1024:256;
        // float fAmp = 0.0;
        // printf("H自动校准触发第%d通道,总采样点数%d.",k,txCalibSrc.m_simpleNum);
        // printf("{ ");
        // for(int i=0;i<x;i++) {
        //     I_date = (int)(txCalibSrc.m_iqBuffer[i] & 0xffffffff);  
        //     Q_date = (int)((txCalibSrc.m_iqBuffer[i] >> 32) & 0xffffffff);  

        //     fAmp = math_amp_calculate(Q_date, I_date); 
        //     printf("%f, ",fAmp);
        // }
        // printf("}\n");
        // if(k == 0 || k == 31) {
        //     printf("自动校准触发第%d通道,采样点数%d.",k,txCalibSrc.m_simpleNum);
        //     printf("{ ");
        //     int x = (txCalibSrc.m_simpleNum > 1024)?256:txCalibSrc.m_simpleNum;
        //     for(int i=0;i<x;i++)
        //     {
        //         printf("0x%lx, ",txCalibSrc.m_iqBuffer[i]);
        //     }
        //     printf(" }\n");
        // }
        
    }

    Sendto(uio_h_sendPolar); 

    //提取V极化发射自动校准数据
    memset(m_amp, 0, sizeof(m_amp));  
    memset(m_phase, 0, sizeof(m_phase));  
    for (int k = 0; k < 32; k++)  //按每0x8000偏移取每个通道的IQ值
    {  
        txCalibSrc.m_simpleNum = 0;  
        txCalibSrc.m_prtNum = 0;  
        
        memorySwap(m_memFile, ((TX_CALIB_BASEADDR + TX_CALIB_OFFSET * 3) + TX_CALIB_CHN_OFFSET * k),  
            (unsigned char *)&txCalibSrc, sizeof(txCalibSrc), nullptr, 0);  
#if (FFTW_ENABLE == 0)
        I_date = (int)(txCalibSrc.m_iqBuffer[nCount] & 0xffffffff);  
        Q_date = (int)((txCalibSrc.m_iqBuffer[nCount] >> 32) & 0xffffffff);  

        m_amp[k] = math_amp_calculate(Q_date, I_date);  
        m_phase[k] = math_phase_calculate(Q_date, I_date);  

#else

        auto result= fftTask(txCalibSrc.m_simpleNum ,txCalibSrc.m_iqBuffer);
        
        m_amp[k] = result.first;
        m_phase[k] = result.second;


        // int x = (txCalibSrc.m_simpleNum > 2000)?1024:256;
        // float fAmp = 0.0;
        // printf("V自动校准触发第%d通道,总采样点数%d.",k,txCalibSrc.m_simpleNum);
        // printf("{ ");
        // for(int i=0;i<x;i++) {
        //     I_date = (int)(txCalibSrc.m_iqBuffer[i] & 0xffffffff);  
        //     Q_date = (int)((txCalibSrc.m_iqBuffer[i] >> 32) & 0xffffffff);  

        //     fAmp = math_amp_calculate(Q_date, I_date); 
        //     printf("%f, ",fAmp);
        // }
        // printf("}\n");

#endif
        
    }
   
    Sendto(uio_v_sendPolar); 

    //提取H极化接收自动校准数据
    memset(m_amp, 0, sizeof(m_amp));  
    memset(m_phase, 0, sizeof(m_phase));
    rxCalibSrc.m_simple = 0;  
    rxCalibSrc.m_prtNum = 0;    
    memorySwap(m_memFile, (RX_CALIB_BASEADDR + RX_CALIB_OFFSET * 2),  
            (unsigned char *)&rxCalibSrc, sizeof(rxCalibSrc), nullptr, 0); 

#if (FFTW_ENABLE == 0)
    for(int k = 0;k<32; k++) {
        I_date = (int)(rxCalibSrc.m_iqBuffer[nCount][k] & 0xffffffff);  
        Q_date = (int)((rxCalibSrc.m_iqBuffer[nCount][k] >> 32) & 0xffffffff);  

        m_amp[k] = math_amp_calculate(Q_date, I_date);  
        m_phase[k] = math_phase_calculate(Q_date, I_date); 

    }
#else
    //接收校准数据缓存
    vector<uint64_t>rxCalibChannelData;
    rxCalibChannelData.resize(rxCalibSrc.m_simple);
    for (int j = 0;j<32;j++) {
        for(int l=10;l<rxCalibSrc.m_simple;l++) {
            rxCalibChannelData[l] = rxCalibSrc.m_iqBuffer[l][j];
        }
        auto result= fftTask(rxCalibSrc.m_simple ,rxCalibChannelData.data());
        m_amp[j] = result.first;
        m_phase[j] = result.second;

        // int x = (rxCalibSrc.m_simple > 2000)?1024:256;
        // float fAmp = 0.0;
        // printf("H接收自动校准触发第%d通道,总采样点数%d.",j,rxCalibSrc.m_simple);
        // printf("{ ");
        // for(int i=0;i<x;i++) {
        //     I_date = (int)(rxCalibChannelData[i] & 0xffffffff);  
        //     Q_date = (int)((rxCalibChannelData[i] >> 32) & 0xffffffff);  

        //     fAmp = math_amp_calculate(Q_date, I_date); 
        //     printf("%f, ",fAmp);
        // }
        // printf("}\n");

    }
    rxCalibChannelData.clear();
#endif


    Sendto(uio_h_recvicePolar);

    //提取V极化接收自动校准数据
    memset(m_amp, 0, sizeof(m_amp));  
    memset(m_phase, 0, sizeof(m_phase));
    rxCalibSrc.m_simple = 0;  
    rxCalibSrc.m_prtNum = 0;    
    memorySwap(m_memFile, (RX_CALIB_BASEADDR + RX_CALIB_OFFSET * 3),  
            (unsigned char *)&rxCalibSrc, sizeof(rxCalibSrc), nullptr, 0); 

#if (FFTW_ENABLE == 0)
    for(int k = 0;k<32; k++) {
        I_date = (int)(rxCalibSrc.m_iqBuffer[nCount][k] & 0xffffffff);  
        Q_date = (int)((rxCalibSrc.m_iqBuffer[nCount][k] >> 32) & 0xffffffff);  

        m_amp[k] = math_amp_calculate(Q_date, I_date);  
        m_phase[k] = math_phase_calculate(Q_date, I_date); 
        
    }
#else
    for (int j = 0;j<32;j++) {
        for(int l=10;l<rxCalibSrc.m_simple;l++) {
            rxCalibChannelData[l] = rxCalibSrc.m_iqBuffer[l][j];
        }
        auto result= fftTask(rxCalibSrc.m_simple ,rxCalibChannelData.data());
        m_amp[j] = result.first;
        m_phase[j] = result.second;

        // int x = (rxCalibSrc.m_simple > 2000)?1024:256;
        // float fAmp = 0.0;
        // printf("V接收自动校准触发第%d通道,总采样点数%d.",j,rxCalibSrc.m_simple);
        // printf("{ ");
        // for(int i=0;i<x;i++) {
        //     I_date = (int)(rxCalibChannelData[i] & 0xffffffff);  
        //     Q_date = (int)((rxCalibChannelData[i] >> 32) & 0xffffffff);  

        //     fAmp = math_amp_calculate(Q_date, I_date); 
        //     printf("%f, ",fAmp);
        // }
        // printf("}\n");
    }
    rxCalibChannelData.clear();

#endif


    Sendto(uio_v_recvicePolar);




}

void Uio::irq1Handle(Uio *argc)  
{  
    const int MAX_EVENTS = INTC_FILES - 4;  

    int j, irq_on = 1,real_read = 0,m_ready = 0,icount = 0;
    // int64_t g_iclock = 0;  
    // double timeout = 0;  
    
    struct pollfd fds[MAX_EVENTS];
    pthread_setname_np(pthread_self(), "irq1Handle");  
    for (j = 0; j < MAX_EVENTS; j++)
    {
        fds[j].fd = argc->intcFd[j];
        fds[j].events = POLLIN;                    // 请求类型是 普通或优先级带数据可读
        if (write(fds[j].fd, &irq_on, sizeof(irq_on)) < 0) {
            qlog_e("intcFd error:%d",argc->intcFd[j]);
        } // 使能中断，每次触发后都需要重新使能
    }

    while (argc->m_isRunning)  
    {  
        m_ready = poll(fds, MAX_EVENTS, -1);// 检查可读事件
        if (m_ready == -1)
        {
            perror("poll error:");
        }
        for (j = 0; j < MAX_EVENTS; j++)
        {
            if (fds[j].revents & POLLIN)
            {
                // qlog_i("irq1 intcFd interrupt :%d", i);
                if (j == 0) {   // 适配卡时序发生器DMA错误中断 
                    qlog_e("适配卡时序发生器DMA错误中断已产生..");
                }
                if (j == 1) {    //发射校准数据传输DMA错误中断
                    qlog_e("发射校准数据传输DMA错误中断已产生..");
                }
                if (j == 2) {   /* AD组件原始数据观测DMA中断 */ 
                      //接收观测通道
                    qlog_i("AD组件原始数据观测DMA中断已产生..");
                    //取出帧头判断采样数据
                    // sem_post(&argc->g_obsSem);
                    // timeout = (double)((time_now() - g_iclock) / 1000);  
                    // qlog_n("intc[2]:clock=%0.3fms", (timeout / 1000));  
                    // g_iclock = time_now();  
                }
                 // DBF原始数据观测DMA中断
                if (j == 3) {
                    qlog_i("DBF原始数据观测DMA中断已产生..");
                    sem_post(&argc->g_dbfSem);
                }
                //AXI中断控制器中断
                if (j == 4) {
                    qlog_i("AXI中断控制器中断已产生..");
                }
                if (j == 5) {    //锁定检测GPIO中断
                    qlog_i("锁定检测GPIO中断已产生..");
                    Server::Instance().m_sxk.getLockStatus();
                }
                real_read = read(fds[j].fd, &icount, 4);
                if (real_read != 4){
                    qlog_e("irq1 read:%d", real_read);
                }
                if (write(fds[j].fd, &irq_on, sizeof(irq_on)) < 0) {
                    qlog_e("enable irq1:%d", fds[j].fd);
                }
            }
        }
    }

}

/**
 * @description: 计算幅度相位
 * @param {calibration_uio} *argc
 * @return {*}
 */
void Uio::topHalfWork(Uio *argc)
{
    int j = 0;
    pthread_setname_np(pthread_self(),"topHalfWork");
    while (argc->m_isRunning)
    {

        {
            unique_lock<mutex> m_gaurd(g_iq0Mutex);
            g_uio0Cond.wait(m_gaurd, []{ return !iq0Queue.empty(); });
            for(j=0;j<16;j++) {
                darktsPackage[j] = iq0Queue.front();
                iq0Queue.pop();////弹出队首元素
            }  
        }
        argc->darktsHandle(uio_top);
        qlog_n("iq0 interrput data handle.");
        
    }
}
/**
 * @description: 计算幅度相位
 * @param {calibration_uio} *argc
 * @return {*}
 */
void Uio::bottomHalfWork(Uio *argc)
{
    int j = 0;
    pthread_setname_np(pthread_self(),"bottomHalfWork");
    while (argc->m_isRunning)
    {
        {
            unique_lock<mutex> m_gaurd(g_iq1Mutex);
            g_uio1Cond.wait(m_gaurd, []{ return !iq1Queue.empty(); });
            for(j=16;j<32;j++) {
                darktsPackage[j] = iq1Queue.front();
                iq1Queue.pop();////弹出队首元素
            }  
        }
        argc->darktsHandle(uio_bottom);
        qlog_n("iq1 interrput data handle.");

    }
}


/*** 
 * @description: 观测处理线程
 * @param {Uio} *argc
 * @return {*}
 */
void Uio::work(Uio *argc)
{
    while (argc->m_isRunning)
    {
        sem_wait(&argc->g_obsSem);
        std::this_thread::sleep_for(std::chrono::milliseconds(20));
        if ( uio_dbf_observer ==  argc->m_workStatus) { //DBF系数观测
            argc->obsDbfHandle();
           
        }
        if( uio_rx_observer ==  argc->m_workStatus ) { //接收校准观测
            argc->obsRxHandle();

        }
        if ( uio_adc_observer == argc->m_workStatus) {  //ADC原始值观测
            argc->obsAdcHandle();

        }
        argc->m_workStatus = uio_noReply;//复位
    }
}

void Uio::txObsWork(Uio *argc)
{
    while (argc->m_isRunning)
    {
        if ( uio_tx_observer == argc->m_workStatus) { //持续观测通道IQ
            argc->obsTxHandle();
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void Uio::obsTxHandle()
{
    int i = 0,j = 0;
    unsigned long base = ((TX_OBSIQ_BASEADDR + m_txWork.m_channel * TX_OBS_CHN_OFFSET) 
                        + m_txWork.m_runCount * TX_OBS_OFFSET);

    memorySwap(m_memFile, base, (unsigned char *)&m_txObs, 32, nullptr, 0); //提取帧头

    if(DATA_NORMAL_HANDER == m_txObs.frame_header) { //判断数据帧头

        if(m_txWork.m_beamCode == m_txObs.beam_code) { //提取波位成功

            // qlog_i("TX观测通道帧头正确..");
            memorySwap(m_memFile, base, (unsigned char *)&m_txObs, sizeof(m_txObs), nullptr, 0); 

            memcpy((unsigned char *)&m_txUpdateObs,(unsigned char *)&m_txObs,32);//赋值帧头
            m_txUpdateObs.tatol_simple = m_txUpdateObs.simple_num[0] + m_txUpdateObs.simple_num[1]
                                    + m_txUpdateObs.simple_num[2] + m_txUpdateObs.simple_num[3]; //计算当前帧所有的采样点
            
            j = 0;
            int freq = (m_txWork.m_freqPoint > 1)?0:m_txWork.m_freqPoint;
            for (i = 0;i < 4094;i++) {  //提取每个子频点的IQ
                if(m_txObs.m_iqBuffer[i][freq] != 0) { //提取指定频点
                    //提取每个子频点的IQ
                    m_txUpdateObs.m_iqBuffer[j] = m_txObs.m_iqBuffer[i][freq];//按照数据结构偏移4个
                    j++;
                }
            }
            
        }
        if(m_txWork.update) {
            m_txWork.update = false;
            txObsData.clear();//清除上一次的数据结构
            //数据回复
            txObsData.push_back(m_txWork.m_channel);
            txObsData.push_back(m_txWork.m_beamCode);
            txObsData.push_back(m_txWork.m_freqPoint);
            //将取出来的数据的帧头32个字节打包
            txObsData.insert(txObsData.end(),(uint8_t *)&m_txUpdateObs,(uint8_t *)&m_txUpdateObs+32);
            //保留每个采样点数占8个字节+32+6个已用长度
            txObsData.reserve(m_txUpdateObs.tatol_simple * 8 + 32 + 6);
            for(i = 0;i < m_txUpdateObs.tatol_simple; i++) { //按照数据结构设置
                // 将 uint64_t 的每个字节拆分并放入 vector  
                for (j = 0; j < 8; j++) {  
                    txObsData.push_back(static_cast<uint8_t>((m_txUpdateObs.m_iqBuffer[i] >> (j * 8)) & 0xFF));  
                } 
            }
            m_pub->pulish(uio_tx_observer,txObsData);
        }
        
    } else {
        qlog_e("TX观测通道获取的帧头错误,数据无效..");
    }
    //循环数据组
    m_txWork.m_runCount = ( m_txWork.m_runCount > 127 )?0:(m_txWork.m_runCount + 1);
}

/*** 
 * @description: DBF观测
 * @return {*}
 */
void Uio::obsDbfHandle()
{
    qlog_i("DBF观测通道任务开启..");
         
    int i = 0,a = 0,b = 0;
    rxDbfObsData.clear();//清除上一次的数据结构
    //提取出DBF数据帧头
    memorySwap(m_memFile, DBF_OBSIQ_BASEADDR,(unsigned char *)&m_rxDbfObs, 16, nullptr, 0); 

    //数据回复
    rxDbfObsData.insert(rxDbfObsData.end(),(uint8_t *)&m_dbfWork,(uint8_t *)&m_dbfWork+sizeof(struct dbfObsWork));
    //帧头打包
    rxDbfObsData.insert(rxDbfObsData.end(),(uint8_t *)&m_rxDbfObs,(uint8_t *)&m_rxDbfObs+16);

    if(m_dbfWork.m_polar > 0) {//获取V极化
        //计算上报指定波束0-15
        a = m_dbfWork.m_channel*2+1;
    } else {    //获取H极化
        a = m_dbfWork.m_channel*2;
    }
    //上报的最大采样点
    b = (m_dbfWork.m_simple > m_rxDbfObs.m_simple)?m_rxDbfObs.m_simple:m_dbfWork.m_simple;
    //保留每个采样点数占8个字节+16（固定帧头）+4个回复已用长度
    rxDbfObsData.reserve(b * 8 + 20);
    //读取16个字节帧头+simple采样点*32（H16个波束+V16个波束）*8个字节的数据
    uint64_t len = (b * 32 *8 + 16);
    memorySwap(m_memFile, DBF_OBSIQ_BASEADDR,(unsigned char *)&m_rxDbfObs, len, nullptr, 0);
    
    for(i = 0;i < b; i++) {
        // 将 uint64_t 的每个字节拆分并放入 vector  
        for (int j = 0; j < 8; j++) {  
            rxDbfObsData.push_back(static_cast<uint8_t>((m_rxDbfObs.m_iqBuffer[i][a] >> (j * 8)) & 0xFF));  
        } 
    }
    m_pub->pulish(uio_dbf_observer,rxDbfObsData);
}

/*** 
 * @description: 接收IQ观测数据源选择
 * @return {*}
 */
void Uio::obsRxHandle()
{
    qlog_i("RX 观测通道任务开启..");
         
    int i = 0,a = 0,b = 0;
    rxObsData.clear();//清除上一次的数据结构
    //提取出DBF数据帧头
    memorySwap(m_memFile, RX_OBSIQ_BASEADDR,(unsigned char *)&m_rxObs, 8, nullptr, 0); 
    //数据回复
    rxObsData.insert(rxObsData.end(),(uint8_t *)&m_rxWork,(uint8_t *)&m_rxWork+sizeof(struct rxObsWork));
    //帧头打包
    rxObsData.insert(rxObsData.end(),(uint8_t *)&m_rxObs,(uint8_t *)&m_rxObs+8);
    // 选择通道0-31
    a = m_rxWork.m_channel;
    //上报的最大采样点
    b = (m_rxWork.m_simple > m_rxObs.m_simple)?m_rxObs.m_simple:m_rxWork.m_simple;
    //保留每个采样点数占8个字节+8+5个已用长度
    rxObsData.reserve(b * 8 + 13);
    //读取8个字节帧头+simple采样点*32*8个字节的数据
    uint64_t len = (b * 32 * 8 + 8);
    memorySwap(m_memFile, RX_OBSIQ_BASEADDR,(unsigned char *)&m_rxObs, len, nullptr, 0);
    
    for(i = 0;i < b; i++) {
        // 将 uint64_t 的每个字节拆分并放入 vector  
        for (int j = 0; j < 8; j++) {  
            rxObsData.push_back(static_cast<uint8_t>((m_rxObs.m_iqBuffer[i][a] >> (j * 8)) & 0xFF));  
        } 
    }
    m_pub->pulish(uio_rx_observer,rxObsData);
}

void Uio::obsAdcHandle()
{
    qlog_i("adc 观测通道任务开启..");

    int i = 0,a = 0,b = 0;
    adcObsData.clear();
    a = m_adcWork.m_channel;
    b = m_adcWork.m_simple * 8;//每个采样点8个字节

    //数据回复
    adcObsData.insert(adcObsData.end(),(uint8_t *)&m_adcWork,(uint8_t *)&m_adcWork+sizeof(struct adcObsWork));
    //提取出ADC数据
    memorySwap(m_memFile, ADC_OBS_BASEADDR,(unsigned char *)&m_adcObs, b, nullptr, 0); 
    qlog_i("adc 观测任务读取的数据.");
    qlog_hexdump("adc",8,(unsigned char *)&m_adcObs,64);
    for(i = 0;i < m_adcWork.m_simple; i++) {
        // 将 uint16_t 的每个字节拆分并放入 vector  
        adcObsData.push_back(static_cast<uint8_t>(m_adcObs.m_adcSrc[i][a] & 0xFF));
        adcObsData.push_back(static_cast<uint8_t>((m_adcObs.m_adcSrc[i][a] >> 8) & 0xFF));
    }

    m_pub->pulish(uio_adc_observer,adcObsData);
}

/*** 
 * @description: 用于触发观测通道
 * @param {uioMode} m
 * @return {*}
 */
void Uio::tiggerObsSem(uioMode m)
{
    uint32_t ret = 0;
    uint8_t data[4];

    if (!Server::Instance().m_sxk.getLockStatus()) {
        qlog_e("触发观测通道失败，时钟未锁定.");
        return ;
    }
    m_workStatus = m;
    switch(m)
    {
        case uio_tx_observer:
            {
                qlog_i("触发发射持续观测通道模式.(此模式需要开启时序)");

                ret = Xil_Out32(HARDWARE_TEST_BASEADDR+152);
                memcpy(data,&ret,4);
                //开启对应通道，观测DMA通道选择
                //byte3 DBF数据源选择	 byte2 调频方向反向	byte1 观测DMA通道选择	byte0 发射校准波位设置
                data[1] = data[1] | (0x01<<m_txWork.m_channel);
                memcpy(&ret,data,4);
                Xil_In32(HARDWARE_TEST_BASEADDR+152,ret);
            }
        break;
        case uio_rx_observer:
            qlog_i("触发接收观测通道模式.");
            {
                ret = 0x01;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        case uio_dbf_observer:
            { //byte2
                ret = 0x10000;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        case uio_adc_observer:
            {
                qlog_i("触发ADC原始值观测数据");
                ret = 0x01010000;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
                ret = 0x00000000;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
                sem_post(&g_obsSem);
            }
        break;
        case uio_rx_obsChan0:
            { //byte2
                qlog_i("触发接收IQ观测数据源选择0:H极化频点0数据");
                ret = 0x0001;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        case uio_rx_obsChan1:
            { //byte2
                qlog_i("触发接收IQ观测数据源选择1:H极化频点1数据");
                ret = 0x0101;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        case uio_rx_obsChan2:
            { //byte2
                qlog_i("触发接收IQ观测数据源选择2:V极化频点0数据");
                ret = 0x0201;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        case uio_rx_obsChan3:
            { //byte2
                qlog_i("触发接收IQ观测数据源选择3:V极化频点1数据");
                ret = 0x0301;
                Xil_In32(RX_OBSIQ_TRIGGER_BASEADDR,ret);
            }
        break;
        default:
        break;
    }

    
}

/*** 
 * @description: 获取起始点和终止点之间的有效波束数0-15
 * @param {int} i
 * @return {*}
 */
int Uio::sysRevDarktsBeamPoint(int i)
{
    int m_sysFreqMode = Server::Instance().m_sxk.beamParamReg[i][2];//频点模式
    int m_Point = 0;
    if(m_sysFreqMode == 0) {
        m_Point = abs(Server::Instance().m_sxk.beamParamReg[i][4] - Server::Instance().m_sxk.beamParamReg[i][3]) + 1;//可用的接收波束信息
    } else {
        m_Point = abs(Server::Instance().m_sxk.beamParamReg[i][6] - Server::Instance().m_sxk.beamParamReg[i][5]) + 1;//可用的接收波束信息
    }
    return m_Point;
}


#define MAX_DARKTS_SIZE sizeof(darktsPrtSend)

// #define TYPE_MODE(x)      

/**
 * @description: 打包PC数据上传发射波束测试数据-时序卡到暗室PC 暗室测试数据发射波位->PC
 * @return {*}
 */
void Uio::dataPackage(int m)
{
    static dataType m_Cmd;
    uint8_t m_cmdData[20];
    vector<float> singleSampleData_hamp,singleSampleData_vamp,singleSampleData_hphase,singleSampleData_vphase;
    uint32_t data_temp[3];
    uint8_t struct_len = 12;
    int revLen=0;
    int dataLen = 0;
    int i=0,j=0,k=0;
    unsigned long g_usLength = 0;
    int m_debug = Server::Instance().m_sxk.m_datktsConf.m_debug;        //用于调试日志
    int m_taskBeamNum = Server::Instance().m_sxk.m_controlReg.m_taskBeamNum; //记录有效波位数
    int m_taskBeamPrt[32];//用于记录系统参数内每个波位内的有效prt个数
    int m_totalPrtNum = 0;
    int m_taskBeamPoint = 0;
    

    DarktsUpdateVct.clear();//先清空发送的暗室数据TCP容器。

    m_taskBeamPoint = sysRevDarktsBeamPoint(0);//(1-16)

    for (i = 0;i<32; i++) {
        m_taskBeamPrt[i] = Server::Instance().m_sxk.beamParamReg[i][9]; //提取所有波位内的波束个数
    }
    //计算需要配置的总波束数
    for(i = 0; i< m_taskBeamNum; i++) {
        m_totalPrtNum += m_taskBeamPrt[i];
    }

    data_temp[0] = Server::Instance().m_sxk.m_datktsConf.m_Item1;//外部触发总数
    if (Server::Instance().m_sxk.m_datktsConf.m_Item4 == 0) { //接收

        data_temp[1] = m_taskBeamNum * m_taskBeamPoint;//任务波位数×有效波束数
        dataLen = data_temp[0]* m_taskBeamNum * 4 * sizeof(float) * m_taskBeamPoint;//波位个数×每个波位4个数据（HV幅相）×4字节占×支持的波束数×总采样点
    } else {    //发射

        data_temp[1] = m_taskBeamNum;//任务波位数
        dataLen = data_temp[0] * m_taskBeamNum * 4 * sizeof(float);//*外部触发×波位个数×每个波位4个数据（HV幅相）×4字节占
    }
    if (Server::Instance().m_sxk.beamParamReg[0][9] > 1 && Server::Instance().m_sxk.m_datktsConf.m_Item4 == 2) //CPI0内PRT0个数
    {
        // data_temp[2] = Server::Instance().m_sxk.m_datktsConf.m_Item4;
        data_temp[2] = 3;
    } else { //PRT0激励脉冲种类
        data_temp[2] = 1;//H极化有效，要V极化有效只能设置起始V，且只设置一个PRT个数
    }

    qlog_i("TCP打包中,外部触发总数:%d,任务波位数:%d,时序参数波束数:%d,波束字节长度:%ld.",data_temp[0],data_temp[1],m_totalPrtNum,dataLen);

    g_usLength = (dataLen+struct_len+sizeof(data_temp));//tcp上报总长度

    if( g_usLength > MAX_DARKTS_SIZE){
        qlog_e("TCP上报总长度超过最大容器:%ld.",g_usLength);
        memset(&darktsPrtSend,0,sizeof(darktsPrtSend));
        return;
    }

    // 将数据追加到 DarktsUpdateVct  
    auto appendVectorToUint8Vector = [&](std::vector<float>&source) {  
        // 获取源数据的指针和大小  
        size_t sizeInBytes = source.size() * sizeof(float);  
        uint8_t* bytes = reinterpret_cast<uint8_t*>(source.data());  // 获取源数据的指针  
        // 预先确保 DarktsUpdateVct 有足够的空间  
        DarktsUpdateVct.reserve(DarktsUpdateVct.size() + sizeInBytes);  
        // 追加数据  
        DarktsUpdateVct.insert(DarktsUpdateVct.end(), bytes, bytes + sizeInBytes);
    };  
    
    //拷贝item,12个字节
    for(i = 0;i<(int)sizeof(data_temp);i++) {
        uint8_t *byte = reinterpret_cast<uint8_t*>(data_temp);
        DarktsUpdateVct.push_back(*(byte + i));
    }
    
    if (m == 1) { //发射模式
        int m_beamCount = 0;
        for(i=0;i<(int)data_temp[0];i++) {//按触发采样点位置保存数据

            for(j=0;j < darktsPrtSend[i].beamNum;j++) { //循环每个波位中有效的prt个数
                for(k=0;k<darktsPrtSend[i].prtNum[j];k++) { //按照prt个数来放置当前位置当前波位的HV极化数据。
                    
                    if( darktsPrtSend[i].prtPolarInfo[k] == FIRE_POLAR_H)  {
                        singleSampleData_hamp.push_back(darktsPrtSend[i].hamp[j][k]); //保存一个H幅度
                        singleSampleData_hphase.push_back(darktsPrtSend[i].hphase[j][k]); //保存一个H相位
                    }

                    if( darktsPrtSend[i].prtPolarInfo[k] == FIRE_POLAR_V) { //00 H极化 01 V极化 02 双极化
                        singleSampleData_vamp.push_back(darktsPrtSend[i].vamp[j][k]); //保存一个V幅度
                        singleSampleData_vphase.push_back(darktsPrtSend[i].vphase[j][k]); //保存一个V相位
                    } 
                    
                    m_beamCount++;
                    if (m_debug) {
                        qlog_n("波束计数:%d,波位:%d,prt:%d,极化:%d,H幅度:%0.1f,V幅度:%0.1f,H相位:%0.1f,V相位:%0.1f.",m_beamCount,j,k,
                        darktsPrtSend[i].prtPolarInfo[k],darktsPrtSend[i].hamp[j][k],darktsPrtSend[i].vamp[j][k],
                        darktsPrtSend[i].hphase[j][k],darktsPrtSend[i].vphase[j][k]);
                    }
                }
            }

            /************************************一个采样点的数据排列***********************************************/
            //当前一个位置波束1的H极化幅度～当前位置波束N的H极化幅度
            //当前一个位置波束1的V极化幅度～当前位置波束N的V极化幅度
            //当前一个位置波束1的H极化相位～当前位置波束N的H极化相位
            //当前一个位置波束1的V极化相位～当前位置波束N的V极化相位
            //TODO：2025-08-21 暗室测试中发现HV交替数据放置应该是一行放H,一行放V
            //当前一个位置波束1的H极化幅度～当前位置波束N的H极化幅度
            //当前一个位置波束1的H极化幅度～当前位置波束N的H极化幅度
            //当前一个位置波束1的V极化幅度～当前位置波束N的V极化幅度
            //当前一个位置波束1的V极化幅度～当前位置波束N的V极化幅度
            //当前一个位置波束1的H极化相位～当前位置波束N的H极化相位
            //当前一个位置波束1的H极化相位～当前位置波束N的H极化相位
            //当前一个位置波束1的V极化相位～当前位置波束N的V极化相位
            //当前一个位置波束1的V极化相位～当前位置波束N的V极化相位
            // 追加四个 vector  
            appendVectorToUint8Vector(singleSampleData_hamp);  
            appendVectorToUint8Vector(singleSampleData_vamp);  
            appendVectorToUint8Vector(singleSampleData_hphase);  
            appendVectorToUint8Vector(singleSampleData_vphase);
            singleSampleData_hamp.clear();
            singleSampleData_vamp.clear();
            singleSampleData_hphase.clear();
            singleSampleData_vphase.clear();
            /************************************一个采样点的数据排列********************************************** */
        }

    }
    if (m == 0) {//接收模式
        int recvCount = 0,m_beamCount = 0;
        if(Server::Instance().m_sxk.beamParamReg[0][3] != 0) {
            qlog_e("第0频点的起始波束不为0,接收暗室无法正常工作，请重新设置参数.");
            for (int k=0;k<MAX_DARKTS_SIMPALE;k++) {
                memset(&darktsPrtSend[k],0,sizeof(darktsPrtSend[k]));
            }
            return;
        }
        for(i=0;i<(int)data_temp[0];i++) {//按触发采样点位置保存数据

            for(j=0;j < darktsPrtSend[i].beamNum;j++) { //循环每个波位中有效的prt个数
                
                // recvCount = darktsPrtSend[i].prtNum[j];//计算出当前波位中总共有多少个波束数据
                for(k=0;k<darktsPrtSend[i].prtNum[j];k++) { //按照prt个数来放置当前位置当前波位的HV极化数据。
                    m_beamCount++;
                    recvCount = k * 16;//数据存放偏移量
                    if( darktsPrtSend[i].prtPolarInfo[k] == FIRE_POLAR_H) { //00 H极化 01 V极化 02 双极化
                        for(int p=0;p < m_taskBeamPoint;p++) {
                            singleSampleData_hamp.push_back(darktsPrtSend[i].hamp[j][recvCount + p]); //保存一个H幅度
                            singleSampleData_hphase.push_back(darktsPrtSend[i].hphase[j][recvCount + p]); //保存一个H相位
                        }
                        if(m_debug) {
                            qlog_n("接收模式波束计数:%d,波位:%d,prt:%d,极化:%d,当前波位中支持的波束数:%d,数据偏移:%d.",
                            m_beamCount,j,k,darktsPrtSend[i].prtPolarInfo[k],m_taskBeamPoint,recvCount);
                            for(int p=0;p < m_taskBeamPoint;p++) {
                                qlog_n("H幅度:%0.1f,H相位:%0.1f.",darktsPrtSend[i].hamp[j][recvCount + p]
                                ,darktsPrtSend[i].hphase[j][recvCount + p]);
                            }
                        }
                    }
                    if( darktsPrtSend[i].prtPolarInfo[k] == FIRE_POLAR_V) { //00 H极化 01 V极化 02 双极化
                        for(int p=0;p < m_taskBeamPoint;p++) {
                            singleSampleData_vamp.push_back(darktsPrtSend[i].vamp[j][recvCount + p]); //保存一个V幅度
                            singleSampleData_vphase.push_back(darktsPrtSend[i].vphase[j][recvCount + p]); //保存一个V相位

                            if(m_debug) {
                                qlog_n("接收模式波束计数:%d,波位:%d,prt:%d,极化:%d,当前波位中支持的波束数:%d,数据偏移:%d.",
                                m_beamCount,j,k,darktsPrtSend[i].prtPolarInfo[k],m_taskBeamPoint,recvCount);
                                for(int p=0;p < m_taskBeamPoint;p++) {
                                    qlog_n("V幅度:%0.1f,V相位:%0.1f.",darktsPrtSend[i].vamp[j][recvCount + p]
                                    ,darktsPrtSend[i].vphase[j][recvCount + p]);
                                }
                            }
                        }
                    }
                }
            }
            

            /************************************一个采样点的数据排列***********************************************/
            // 追加四个 vector  
            appendVectorToUint8Vector(singleSampleData_hamp);  
            appendVectorToUint8Vector(singleSampleData_vamp);  
            appendVectorToUint8Vector(singleSampleData_hphase);  
            appendVectorToUint8Vector(singleSampleData_vphase);
            singleSampleData_hamp.clear();
            singleSampleData_vamp.clear();
            singleSampleData_hphase.clear();
            singleSampleData_vphase.clear();
            /************************************一个采样点的数据排列********************************************** */
        }

    }
    
    revLen = DarktsUpdateVct.size();//数据总长度

    //打包帧头
    m_Cmd.head = PROTOCOL_HEAD;
    m_Cmd.cmdType = s_WaveCalibration;
    m_Cmd.cmdChildType = 3;
    m_Cmd.followData = 1;
    m_Cmd.dataLen = revLen;
    m_Cmd.tail = PROTOCOL_TAIL;
    
    memcpy(m_cmdData,(uint8_t *)&m_Cmd,sizeof(m_Cmd));

    DarktsUpdateVct.insert(DarktsUpdateVct.begin(),m_cmdData,m_cmdData+20);
    //打包帧头
    qlog_w("暗室上报数据总长度:%ld,计算方式:有效波位数×每个波位中的波束个数×采样点数×4(2组幅相)×4字节浮点 + 20(cmd).",revLen+20);
    //TODO::2024/4/29 完成了一包暗室后清理所有队列数据
    if ( !iq0Queue.empty() ) {
        while (!iq0Queue.empty()) iq0Queue.pop();
    }
    if ( !iq1Queue.empty() ) {
        while (!iq1Queue.empty()) iq1Queue.pop();
    }
    for (int k=0;k<MAX_DARKTS_SIMPALE;k++) {
        memset(&darktsPrtSend[k],0,sizeof(darktsPrtSend[0]));
    }
    
    size_t ret = Server::Instance().separate(s_pc,1,DarktsUpdateVct.data(),DarktsUpdateVct.size());
    qlog_n("暗室数据完成传输的长度=%d",ret);
    qlog_hexdump("tcp header",16,DarktsUpdateVct.data(),56);
}

//第二版
void Uio::darktsHandle(darkHandleMode m)
{
    int simpleCnt = 0,tmp = 0;
    int i = 0,count = 0; // count 多少个采样点

    static uint16_t prt_cnt = 0, darkts_cnt = 0, darkts_beam = 0,darkts_mode = 0;
    int m_debug = Server::Instance().m_sxk.m_datktsConf.m_debug;        //用于调试日志
    darkts_cnt = Server::Instance().m_sxk.m_datktsConf.m_Item1;         //暗室测试计数
    darkts_beam = Server::Instance().m_sxk.m_controlReg.m_taskBeamNum;  //测试任务波位数,有效波位数
    darkts_mode = Server::Instance().m_sxk.m_datktsConf.m_Item4;        //暗室模式0接收，1发射，2收发
    tmp = Server::Instance().m_sxk.beamList[darkts_beam];//获取波位编号
    prt_cnt = Server::Instance().m_sxk.beamParamReg[tmp - 1][9];//获取波位内的prt0计数

    if(m == uio_bottom){
        i=16;count=32;
    }else{
        i=0;count=16;
    }

    for (; i < count; i++) //按prt处理的循环
    {
        if(darktsPackage[i].m_externelCnt > (MAX_DARKTS_SIMPALE-1) || darktsPackage[i].m_beamCode > 31) {
            qlog_e("错误帧，外部触发计数:%d,波位:%d.",darktsPackage[i].m_externelCnt,darktsPackage[i].m_beamCode);
            // Xil_In32(TIMING_CONFIG_BASEADDR,0x00060004);
            break;
        }

        simpleCnt = darktsPackage[i].m_externelCnt;
        processDarktsData(darkts_mode,darktsPackage[i],darktsPrtSend[simpleCnt],m_debug);
        //判断是否完成测试必须是最后一个点的最后一个波位的最后一个prt
        if (darktsPackage[i].m_externelCnt == (darkts_cnt - 1) && darktsPackage[i].m_beamCode == (darkts_beam - 1) && darktsPackage[i].m_prtCnt == (prt_cnt - 1)) {
            qlog_w("暗室测试完成一列,采样点:%d,波位:%d,prt:%d",darktsPackage[i].m_externelCnt,darktsPackage[i].m_beamCode,darktsPackage[i].m_prtCnt);
            u_DarktsComplete = true;//成功完整处理
        }
    }
}

void Uio::processDarktsData(int darkts_mode, const darktsFrame& package, struct oneSimple_prt_stc& oneSimpe,int m_debug)
{
    static struct darktsAmpPhaseFrame m_data;

    handleFrame(package,m_data);//转换幅度相位
    
    oneSimpe.beamNum = Server::Instance().m_sxk.m_controlReg.m_taskBeamNum; //保存此采样点的有效波位数
    oneSimpe.prtPolarInfo[oneSimpe.prtNum[package.m_beamCode]] = package.m_polar; //保留极化信息
    oneSimpe.prtNum[package.m_beamCode] += 1; //如果这个波位上prt有数据则计数+1，否则为0
    
    if (darkts_mode == 1) { //发射模式
        //发送数据
        if (m_debug) {
            qlog_n("暗室发送模式数据:采样点:%d,波位:%d,prt:%d,极化:%d.",package.m_externelCnt,package.m_beamCode,package.m_prtCnt,package.m_polar);
        }
        processDarktsSendData(package,m_data,oneSimpe);

    } else if (darkts_mode == 0) { //接收模式
        //接收数据
        if (m_debug) {
            qlog_n("暗室接收模式数据:采样点:%d,波位:%d,prt:%d,极化:%d.",package.m_externelCnt,package.m_beamCode,package.m_prtCnt,package.m_polar);
        }
        processDarktsRecvData(package,m_data,oneSimpe);


    } else {
        qlog_n("收发模式不支持，错误:采样点:%d,波位:%d,prt:%d",package.m_externelCnt,package.m_beamCode,package.m_prtCnt);
    }
    if(m_debug) {
        if(package.m_externelCnt < 2) {
            qlog_hexdump("暗室原始数据:",16,(uint8_t *)&package,sizeof(package));
        }
    }
}


void Uio::processDarktsSendData(const darktsFrame& package,const darktsAmpPhaseFrame& m_data,struct oneSimple_prt_stc& oneSimpe)
{
    //一个prt对应一个极化，故可用极化区分PRT
    if (package.m_polar == FIRE_POLAR_H) { //00 H极化 01 V极化 02 双极化
        if(package.m_sendIQ[0][0] == 0 && package.m_sendIQ[0][1] == 0) { //说明这个频点0没有值
            //[采样位置计数]下的[指定波位]的[指定PRT]=保存幅度数据
            oneSimpe.hamp[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[1][0];//H

            //[采样位置计数]下的[指定波位]的[指定PRT]=保存相位数据
            oneSimpe.hphase[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[1][1];//H
        } else {
            //[采样位置计数]下的[指定波位]的[指定PRT]=保存幅度数据
            oneSimpe.hamp[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[0][0];//H

            //[采样位置计数]下的[指定波位]的[指定PRT]=保存相位数据
            oneSimpe.hphase[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[0][1];//H
        }


    } else if(package.m_polar == FIRE_POLAR_V) { //01 V极化,
        if(package.m_sendIQ[0][0] == 0 && package.m_sendIQ[0][1] == 0) { //说明这个频点0没有值
            //位置计数+当前波位保存幅相数据
            oneSimpe.vamp[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[1][0];//V

            oneSimpe.vphase[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[1][1];//V
        } else {
            //位置计数+当前波位保存幅相数据
            oneSimpe.vamp[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[0][0];//V

            oneSimpe.vphase[package.m_beamCode][package.m_prtCnt] 
            = m_data.m_sendAmpPhase[0][1];//V
        }
        

    }
}

/*** 
 * @description: 接收数据放置格式
 * H prt0[0-15] V prt1[16-31]
 * @param {darktsFrame&} package
 * @param {darktsAmpPhaseFrame&} m_data
 * @param {oneSimple_prt_stc&} oneSimpe
 * @return {*}
 */
void Uio::processDarktsRecvData(const darktsFrame& package,const darktsAmpPhaseFrame& m_data,struct oneSimple_prt_stc& oneSimpe)
{
    int recvCount = 0;
    if(package.m_prtCnt > 256) {
        qlog_e("系统参数配置错误,暗室模式下的波位prt数最多只支持256个.");
        return;
    }
    //一个prt对应一个极化，故可用极化区分PRT,由于接收模式下，每次都是16个波束上报，故每个prt都需要保存16组数据
    if (package.m_polar == FIRE_POLAR_H) { //00 H极化 01 V极化 02 双极化
        recvCount = package.m_prtCnt * 16; //每个prt保存16组数据
        for(int j = 0;j < 16;j++) { //保存16组数据
            //[采样位置计数]下的[指定波位]的[指定PRT里16组数据]=保存幅度数据
            oneSimpe.hamp[package.m_beamCode][j + recvCount] 
            = m_data.m_recAmpPhase[j][0];//H

            //[采样位置计数]下的[指定波位]的[指定PRT]=保存相位数据
            oneSimpe.hphase[package.m_beamCode][j + recvCount] 
            = m_data.m_recAmpPhase[j][1];//H
        }

    } else if(package.m_polar == FIRE_POLAR_V) { //01 V极化,
        recvCount = package.m_prtCnt * 16; //每个prt保存16组数据
        for(int j = 0;j < 16;j++) { //保存16组数据
            //[采样位置计数]下的[指定波位]的[指定PRT里16组数据]=保存幅度数据
            oneSimpe.vamp[package.m_beamCode][j + recvCount] 
            = m_data.m_recAmpPhase[j][0];//V

            //[采样位置计数]下的[指定波位]的[指定PRT]=保存相位数据
            oneSimpe.vphase[package.m_beamCode][j + recvCount] 
            = m_data.m_recAmpPhase[j][1];//V
        }

    }
}

/*** 
 * @description: 打包任务
 * @param {Uio} *argc
 * @return {*}
 */
void Uio::packageTask(Uio *argc)
{
    
    while (argc->m_isRunning)
    {
        sem_wait(&argc->g_packageTask);
        if(argc->isPackage) {
            int darkts_mode = Server::Instance().m_sxk.m_datktsConf.m_Item4;        //暗室模式0接收，1发射，2收发
            argc->isPackage = false;
            if (argc->u_DarktsComplete) {//如果完整则直接上报
                argc->dataPackage(darkts_mode);
            } else {
                if ( argc->repairDarkts() ) {
                    argc->dataPackage(darkts_mode);
                }
            }
            
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

/**
 * @description: 帧解析成幅相数据
 * @param {DataPath} route
 * @return {*}
 */
int Uio::handleFrame(const struct darktsFrame& src,struct darktsAmpPhaseFrame& dst)
{
    int i = 0;
    int iData = 0,qData = 0;
    memcpy((uint8_t *)&dst,(uint8_t *)&src,8); // 拷贝头部
    iData = (int)src.m_sendIQ[0][0];
    qData = (int)src.m_sendIQ[0][1];
    dst.m_sendAmpPhase[0][0] = math_amp_calculate(qData, iData);
    dst.m_sendAmpPhase[0][1] = math_phase_calculate(qData, iData); 
    //TODO：将相位改到-180～180
    dst.m_sendAmpPhase[0][1] = convert_angle(dst.m_sendAmpPhase[0][1]);
    iData = (int)src.m_sendIQ[1][0];
    qData = (int)src.m_sendIQ[1][1];
    dst.m_sendAmpPhase[1][0] = math_amp_calculate(qData, iData);
    dst.m_sendAmpPhase[1][1] = math_phase_calculate(qData, iData); 
    //TODO：将相位改到-180～180
    dst.m_sendAmpPhase[1][1] = convert_angle(dst.m_sendAmpPhase[1][1]);

    for (i=0;i<16;i++) {
        iData = src.m_recviceIQ[i][0];
        qData = src.m_recviceIQ[i][1];
        if (iData == 0 && qData == 0) {
            dst.m_recAmpPhase[i][0] = 0;
            dst.m_recAmpPhase[i][1] = 0;
        } else {
            dst.m_recAmpPhase[i][0] = math_amp_calculate(qData, iData);
            dst.m_recAmpPhase[i][1] = math_phase_calculate(qData, iData); 
            //TODO：将相位改到-180～180
            dst.m_recAmpPhase[i][1] = convert_angle(dst.m_recAmpPhase[i][1]);
        }
    }
    return 0;
}

/*** 
 * @description: 例：100个点，计数：0-95（丢4个点），最多只补5个点多了报错。第一个点永远用第二个点替代，，，，不支持单prt和固定极化模式，只能交替极化
 * @return {*}
 */
bool Uio::repairDarkts()
{
    static struct darktsFrame m_finishFrame[32];
    uint16_t darkts_cnt = 0,nCount = 0;
    int m_cnt = 0,m_beam = 0;
    int m_mode = Server::Instance().m_sxk.m_datktsConf.m_Item4;

    int darkts_beam = Server::Instance().m_sxk.m_controlReg.m_taskBeamNum;  //测试任务波位数,有效波位数

    darkts_cnt = Server::Instance().m_sxk.m_datktsConf.m_Item1;         //暗室采样位置数量
    darkts_cnt = (darkts_cnt < MAX_DARKTS_SIMPALE)?darkts_cnt:MAX_DARKTS_SIMPALE;

    for (int k = 0; k < 32; k++) {  //将外部触发点记录下来
        memRead((unsigned long *)&m_finishFrame[k], m_darktsAddr, DARK_OFFSET * k, sizeof(struct darktsFrame));

        m_cnt = m_finishFrame[k].m_externelCnt;
        m_beam = m_finishFrame[k].m_beamCode;

        qlog_n("内存中预留的数据：第%d帧,外部触发:%d,波位号:%d,prt:%d.",k,m_cnt,m_finishFrame[k].m_beamCode,m_finishFrame[k].m_prtCnt);
        //继续处理一次暗室采样点数据
        if(m_finishFrame[k].m_externelCnt < darkts_cnt && m_finishFrame[k].m_beamCode < darkts_beam) {
            
            if(darktsPrtSend[m_cnt].prtNum[m_beam] < (m_finishFrame[k].m_prtCnt + 1)) { //保证不重复补prt
                qlog_w("内存中存在未产生中断的采样点，修补第[%d]个采样点,波位号:%d,prt:%d.",m_cnt,m_beam,m_finishFrame[k].m_prtCnt);
                processDarktsData(m_mode, m_finishFrame[k], darktsPrtSend[m_cnt], 0);//重新补偿相关采样点
            }
            
        }
    }

    //单PRT怎么处理呢？不支持单PRT
    //判断缺少的点是否超过5个
    for(int i=0;i<darkts_cnt;i++)
    {
        vector<int>src(darktsPrtSend[i].prtNum,darktsPrtSend[i].prtNum+32);
        if(sumArray(src) == 0 && i != 0) {
            qlog_e("丢失的暗室采样点:%d.",i);
            if(nCount > 5) { //报错
                qlog_e("丢失触发点数超过5个,无法上报暗室上位机.");
                for (int k=0;k<MAX_DARKTS_SIMPALE;k++) { //TODO:清理数据
                    memset(&darktsPrtSend[k],0,sizeof(darktsPrtSend[k]));
                }
                return false;
            } else {
                nCount++;
            }
        }
    }
    

    memcpy((uint8_t *)&darktsPrtSend[0],(uint8_t *)&darktsPrtSend[1],sizeof(darktsPrtSend[0]));//最后把第二个点补第一个点
    return true;
}


/**
 * @description: 接收校准数据后发出通知告知订阅者
 * @param {uioMode} m
 * @param {unsigned char*} dataIn
 * @param {unsigned int} inLen
 * @return {*}
 */
void transmit::pulish(int m,vector<uint8_t>& dataIn)
{
    if(dataIn.size() == 0) return;

    m_status = m;
    notify(m_status,dataIn);
}
/**
 * @brief: 请求校准数据
 * @param {int} m
 * @return {*}
 */
void transmit::request(int m)
{
    uioMode mode = (uioMode) m;
    auto ret = wait(5000);//阻塞
    m_notifyFinish = false;
     if(ret) {
        switch(mode)
        {
            case uio_h_sendPolar:
                Server::Instance().m_sxk.m_controlReg.m_timingStatus = TIME_H_SEND_CALL;//H极化发射校准
                Server::Instance().m_event.triggerEvent(WRITE_CONTROL_REG);//启动写入控制寄存器
                qlog_w("触发 H发射校准.");
                break;
            case uio_v_sendPolar:
                Server::Instance().m_sxk.m_controlReg.m_timingStatus = TIME_V_SEND_CALL;//V极化发射校准
                Server::Instance().m_event.triggerEvent(WRITE_CONTROL_REG);//启动写入控制寄存器
                qlog_w("触发 V发射校准.");
                break;
            case uio_h_recvicePolar:
                Server::Instance().m_sxk.m_controlReg.m_timingStatus = TIME_H_REVICE_CALL;//H极化接收校准
                Server::Instance().m_event.triggerEvent(WRITE_CONTROL_REG);//启动写入控制寄存器
                qlog_w("触发 H接收校准.");
                break;
            case uio_v_recvicePolar:
                Server::Instance().m_sxk.m_controlReg.m_timingStatus = TIME_V_REVICE_CALL;//V极化接收校准
                Server::Instance().m_event.triggerEvent(WRITE_CONTROL_REG);//启动写入控制寄存器
                qlog_w("触发 V接收校准.");
                break;
            case uio_noReply:
                m_notifyFinish = true;//保证了下一次校准满足条件变量
                qlog_i("完成一次触发，复位.");
                break;
            default:
                qlog_e("校准模式触发错误.");
            break;
        }
    } else {
        qlog_e("请求校准数据,阻塞超时错误!");
    }
}

